package br.com.petsis.session;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;

import br.com.petsis.entity.Empresa;
import br.com.petsis.entity.Funcionalidade;
import br.com.petsis.entity.PerfilFuncionalidade;
import br.com.petsis.entity.Usuario;
import br.com.petsis.utilitarios.UtilDate;
import br.com.petsis.utilitarios.UtilString;

@Name("authenticator")
public class Authenticator
{
	private static final String QRY_USUARIO = "select u from Usuario u where u.dscUsuario = :dscUsuario and u.flgAtivo = 'T' ";
	private static final String QRY_PERFIL = "select pf.flg_leitura,pf.flg_gravacao,pf.flg_exclusao,pf.flg_desconto,pf.id_funcionalidade from perfil_funcionalidade pf where pf.id_perfil = :idPerfil";
	private static final String QRY_FUNCIONALIDADE = "select f.dsc_descricao from funcionalidade f where f.flg_ativo = 'T'";
	private static final String PARAMETER_DSC_USUARIO = "dscUsuario";
	private static final String SENHA_ADMIN = "Ami2012";
	
    @Logger private Log log;

    @In Identity identity;
    @In Credentials credentials;
    @In(create=true)
    private EntityManager entityManager;
    
    @Out(scope=ScopeType.SESSION, required=false)
    private Usuario usuarioLogado;
    
    @Out(scope=ScopeType.SESSION, required=false)
    private Empresa empresaSessao;

	public boolean authenticate()
    {
    	try{
    		Usuario user = (Usuario)entityManager.createQuery(QRY_USUARIO)
    			.setParameter(PARAMETER_DSC_USUARIO, credentials.getUsername())
    			.getSingleResult();
    		if(user.getDscSenha().equals(UtilString.md5(credentials.getPassword()))){
    			if(user.getEmpresa() != null){
    				if(UtilDate.data1MenorOuIgualQueData2(user.getEmpresa().getDtaValidade(),new Date())){
    					return false;
    				}
    			}
    			log.info("authenticating {0}", credentials.getUsername());
    			usuarioLogado = user;
    			empresaSessao = user.getEmpresa();
    			registraDataUltimoAcesso(user);
    			addRolesUser();
                return true;
    		}
    	}catch(NoResultException e){
    		if(credentials.getUsername().equals("admin")
    				&& credentials.getPassword().equals(SENHA_ADMIN)){
    			identity.addRole("admin");
    			usuarioLogado = new Usuario();
    			usuarioLogado.setDscNome(credentials.getUsername());
    			usuarioLogado.setDscUsuario(credentials.getUsername());
    			usuarioLogado.setDtaUltimoAcesso(UtilDate.getDataAtual());
    			empresaSessao = null;
    			List<String> funcionalidades = entityManager.createNativeQuery(QRY_FUNCIONALIDADE).getResultList();
    			for(String f : funcionalidades){
    				if(f != null){
	    				identity.addRole(f+"_LER");
	    				identity.addRole(f+"_GRAVAR");
	    				identity.addRole(f+"_EXCLUIR");
	    				identity.addRole(f+"_DESCONTO");
    				}
    			}
    			return true;
    		}else{
    			try{
    				Usuario user = (Usuario)entityManager
    					.createQuery("select u from Usuario u where UPPER(u.cliente.dscEmail) = UPPER(:email)")
    					.setParameter("email", credentials.getUsername())
    					.getSingleResult();
    				if(user.getDscSenha().equals(UtilString.md5(credentials.getPassword()))){
    					log.info("authenticating {0}", credentials.getUsername());
    					usuarioLogado = user;
    					empresaSessao = user.getCliente().getEmpresa();
    					registraDataUltimoAcesso(user);
    					addRolesUser();
    					return true;
    				}
    			}catch (NoResultException n) {
    				return false;
				}
    		}
    		return false;
    	}
        
        return false;
    }
	
	private void registraDataUltimoAcesso(Usuario usuario){
		/*usuario.setDtaUltimoAcesso(new Date());
		entityManager.merge(usuario);
		entityManager.flush();*/
	}
	
	private void addRolesUser(){
		List<Object[]> permissoes = entityManager.createNativeQuery(QRY_PERFIL)
			.setParameter("idPerfil", usuarioLogado.getPerfil().getIdPerfil())
			.getResultList();
		for(Object[] o : permissoes){
			if(o[0] != null && o[0].toString().equals("T")){
				identity.addRole(o[4] != null ? recuperaDescricaoFuncionalidade(Integer.parseInt(o[4].toString()))+"_LER" : null);
			}
			if(o[1] != null && o[1].toString().equals("T")){
				identity.addRole(o[4] != null ? recuperaDescricaoFuncionalidade(Integer.parseInt(o[4].toString()))+"_GRAVAR" : null);
			}
			if(o[2] != null && o[2].toString().equals("T")){
				identity.addRole(o[4] != null ? recuperaDescricaoFuncionalidade(Integer.parseInt(o[4].toString()))+"_EXCLUIR" : null);
			}
			if(o[3] != null && o[3].toString().equals("T")){
				identity.addRole(o[4] != null ? recuperaDescricaoFuncionalidade(Integer.parseInt(o[4].toString()))+"_DESCONTO" : null);
			}
		}
	}
	
	public String recuperaDescricaoFuncionalidade(Integer id){
		try {
			Object retorno = entityManager.createNativeQuery("select f.dsc_descricao from funcionalidade f where f.id_funcionalidade = :id")
				.setParameter("id", id)
				.getSingleResult();
			return retorno != null ? retorno.toString() : "";
		} catch (NoResultException e) {
			return "";
		}
	}
    
}
